home *** CD-ROM | disk | FTP | other *** search
- ;*************************************************************************
- ;** mmu.library **
- ;** **
- ;** a system library for arbitration and control of the MC68K MMUs **
- ;** **
- ;** © 1998 THOR-Software, Thomas Richter **
- ;** No commercial use, reassembly, modification without prior, written **
- ;** permission of the authors. **
- ;** Including this library in any commercial software REQUIRES a **
- ;** written permission and the payment of a small fee. **
- ;** **
- ;** This is an internal header file, do not depend on anything here. **
- ;** Use the official include files. **
- ;** Distributed only for the mmu.library development group for private **
- ;** use. **
- ;** **
- ;**---------------------------------------------------------------------**
- ;** Unified MMU table builder, Version 0.00 **
- ;** © 1998 THOR-Software **
- ;*************************************************************************
-
- ;FOLD Includes
- include inc:macros.asm
- include inc:exec_lib.asm
- include mu_lib.i
- include mu_context.i
- include mu_alerts.i
- ;ENDFOLD
- ;FOLD External References
- xref LockContext
- xref UnlockContext
- xref MUAlert
- xref FreePointerTable
- ;ENDFOLD
- ;FOLD Defines
- ;ENDFOLD
-
- section main_code,code
-
- machine mc68020
-
- ;FOLD BuildMMUTable
- ;*************************************************
- ;** BuildMMUTable **
- ;** build a new MMU table or rebuild the MMU **
- ;** table for the context *a0 **
- ;*************************************************
- xdef BuildMMUTable
- BuildMMUTable:
-
- illegal
-
- saveregs d2-d5/a3/a5
- move.l a0,a5
- bsr LockContext
-
- moveq #-1,d0 ;return code is fine
- btstm ctxf_dirty,ctx_Flags(a5) ;something requires rebuilding it?
- beq .notdirty ;if this context is not dirty, nothing needs to be done
- tst.b mulib_MMUType(a6) ;A MMU active ?
- beq.s .notdirty ;if not, forget it.
-
- move.l ctx_Mapping(a5),a3 ;get the mapping of this context
- do
- tst.l (a3) ;end of the list?
- break.s eq ;if so, ignore it
- btstm mapf_dirty,map_Flags(a3) ;does this map node require a rebuild ?
- beq.s .next ;if not, get the next
-
- movem.l map_lower(a3),d2-d3 ;read the range of this mapping
- moveq #-1,d4 ;get highest level that allows mapping of this with an early termination
- moveq #1,d5 ;size of the "pages" at this level
- addq.l #1,d3 ;upper and lower bound, upper exclusive
- move.b ctx_LevelABits(a5,d4.w),d0 ;get shift value
- bne.s .shift
-
- do
- addq.l #1,d4 ;next level
- move.b ctx_LevelABits(a5,d4.w),d0 ;read next level
- bne.s .gotbits
- moveq #4,d4 ;we're at page level
- .gotbits:
- cmp.l d2,d3 ;is this now equal?
- beq.s .foundlevel ;if so, we got the right level
- .shift:
- ror.l d0,d5
- lsl.l d0,d2
- lsl.l d0,d3
- cmp.w #4,d4 ;until we are at page level
- while.s lo
-
- pea AN_BadContext ;submit an alert.
- bsr MUAlert ;the context contains
- moveq #0,d0 ;unaligned structures
- bra.s .unlockexit
- .foundlevel: ;d4 is now the level of the
- ;MMU table we've to change
- movem.l map_lower(a3),d2-d3 ;get lower/higher address
- addq.l #1,d3
- do
- ;lower in d2
- bsr FindPageDescriptor ;find the page descriptor that manages this
- beq.s .cleanup
- bsr ModifyPages ;setup the pages
- beq.s .cleanup
- add.l d5,d2
- cmp.l d3,d2 ;all done?
- while.s ne
- .next:
- move.l (a3),a3 ;get the next mode
- loop.s
- ;more to be done here
- moveq #-1,d0
- bra.s .unlockexit
- .cleanup: ;more has to happen here
- moveq #0,d0
- .unlockexit:
- .notdirty:
- move.l a5,a0 ;Context -> a0
- bsr UnlockContext
-
- tst.l d0
- loadregs
- rts
- ;ENDFOLD
- ;FOLD FindPageDescriptor
- ;*************************************************
- ;** FindPageDescriptor **
- ;** Find the page descriptor for address d2 **
- ;** at level d4, return it in d0 **
- ;** *a5=Context **
- ;** Rebuild, if required, intermediate levels **
- ;** of the translation tree **
- ;** return the page/pointer descriptor in d0 **
- ;** or NULL in case of failure **
- ;*************************************************
- FindPageDescriptor:
- move.l d2,d0
- move.l d4,d1
- jsr mulib_FindPage(a6) ;let the MMU specific
- ;routine do the dirty work
- tst.l d0 ;found something ?
- bne.s .exit ;if so, great!
-
- move.l d4,d0
- beq.s .rootlevel
-
- saveregs d4 ;not found.
- ;if so, find and build the parent level of the tree
- do
- subq.l #1,d4
- tst.b mulib_LevelABits(a6,d4.w) ;is this level of the tree available ?
- while.s eq ;if not, retry
-
- ;here: found a valid (non-root) level
- bsr FindPageDescriptor ;find the page descriptor at one level above
- loadregs
- beq.s .exit ;if not found, abort
-
- .rootlevel:
- move.l d0,a1 ;page found -> a1 (is null if root)
- move.l d4,d1 ;this level
- move.l d2,d0 ;this address
- jsr mulib_InsertLevel(a6) ;fill in a copy of the tree at this level
- tst.l d0
- .exit:
- rts
- ;ENDFOLD
- ;FOLD ModifyPages
- ;*************************************************
- ;** ModifyPages **
- ;*************************************************
- ModifyPages:
- rts
- ;ENDFOLD
- ;FOLD FreeMMUTable
- ;*************************************************
- ;** FreeMMUTable **
- ;** free the MMU table of the context *a0 **
- ;** the context MUST be unloaded **
- ;** (has to be ensured by the caller) **
- ;*************************************************
- xdef FreeMMUTable
- FreeMMUTable:
- saveregs a5
-
- move.l ctx_Root(a0),d0 ;a MMU table allocated ?
- beq.s .exit
-
- move.l a0,a5
- moveq #0,d1 ;we're at level A
- move.l d0,a0 ;save the pointer
-
- bsr.s RecursiveRelease ;release this stuff
- .exit:
- loadregs
- rts
- ;ENDFOLD
- ;FOLD RecursiveRelease
- ;*************************************************
- ;** RecursiveRelease **
- ;** Release the tree branch starting at *a0 **
- ;** at level d0, Context *a5 **
- ;*************************************************
- RecursiveRelease:
- saveregs d3-d4/a2-a3
-
- move.l d1,d4 ;keep the level
- move.l a0,a2
- move.l a0,a3
- cmp.w #4,d4 ;are we at page level ?
- beq.s .release ;if so, release immediately
-
- move.l mulib_LevelATableSz(a6,d4.w*4),d3 ;number of entries in this table
- do
- move.l (a2)+,d0 ;read pointer at this level
- move.l d4,d1 ;Level -> d1
- jsr mulib_NextLevel(a6) ;do we have a next level ?
- tst.l d0
- beq.s .nonext ;if not, then forget it
- move.l d4,d1
- move.l d0,a0 ;the table pointer for the next level
- addq.w #1,d1 ;next level
- tst.b mulib_LevelABits(a6,d1.w) ;is this level available ?
- bne.s .gotlevel
- moveq #4,d1 ;if not, we're at page level
- .gotlevel:
- bsr.s RecursiveRelease ;release the level below
- .nonext:
- subq.l #1,d3
- while.s ne
- .release:
- move.l d4,d0 ;at this level
- move.l a3,a1 ;this table
- ;context in a5
- bsr FreePointerTable ;now release this level
-
- loadregs
- rts
- ;ENDFOLD
-
-
-
-
-